﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using University.Workshop.Model;
using University.Workshop.DataAccess;

namespace University.Workshop.Business
{
    public class ManagerCollectControl
    {
        public static ICollection<Model.CollectControl> SearchIncomeByDates(DateTime? initialDate, DateTime? endDate, ref decimal totalMoney)
        {
            if (initialDate == null)
                initialDate = DateTime.MinValue;
            if (endDate == null)
                endDate = DateTime.MaxValue;

            ICollection<Model.CollectControl> waterCollectList = (DataAccess.DataAccessWaterCollectControl.GetBetweenDates(initialDate.Value, initialDate.Value)).Cast<Model.CollectControl>().ToList();
            ICollection<Model.CollectControl> otherCollectList = (DataAccess.DataAccessOtherCollectControl.GetBetweenDates(initialDate.Value, endDate.Value)).Cast<Model.CollectControl>().ToList();
            ICollection<Model.CollectControl> fineCollectList = (DataAccess.DataAccessFineCollectControl.GetBetweenDates(initialDate.Value, endDate.Value)).Cast<Model.CollectControl>().ToList();

            waterCollectList.ToList().ForEach(i => i.Estructura = ((WaterChargeType)(i.CollectType)).ToString());
            otherCollectList.ToList().ForEach(i => i.Estructura = ((OtherChargeType)(i.CollectType)).ToString());
            fineCollectList.ToList().ForEach(i => i.Estructura = ((FineType)(i.CollectType)).ToString());

            ICollection<Model.CollectControl> genericList = (waterCollectList.Union(otherCollectList).Union(fineCollectList)).ToList();
            if (genericList.Count == 0)
            {
                throw new Exception("no existen datos registrados");
            }
            totalMoney = genericList.AsEnumerable().Sum(o => o.PaymentAmount);
            return (from c in genericList
                    orderby c.CollectPayDate ascending
                    select c).ToList();
        }

        public static void UpdateCollects(ICollection<Model.CollectControl> collectControls)
        {
            //DataAccessCharges.UpdateCharges(collectControls);
        }

        public static void RegisterOtherCollect(Model.OtherCollectControl collectControlToRegister)
        {
            DataAccessOtherCollectControl.RegisterOtherCollectControl(collectControlToRegister);
        }

        public static void RegisterFineCollect(Model.FineCollectControl collectControlToRegister)
        {
            DataAccessFineCollectControl.RegisterFineCollectControl(collectControlToRegister);
        }

        public static void RegisterPayment(ICollection<Model.CollectControl> collects, Model.User user)
        {
            Payment p = new Payment();
            p.TotalAmount = 0;
            p.PaymentDate = DateTime.Now;
            p.UserId = user.UserId;
            p.KardexId = collects.First().KardexId;

            System.Type type;

            foreach (CollectControl c in collects)
            {
                p.TotalAmount += c.PaymentAmount;
                p.Charges += c.CollectId + ";";
                c.CollectPayDate = p.PaymentDate;

                type = c.GetType();
                switch (type.BaseType.Name)
                {
                    case "WaterCollectControl":
                        DataAccess.DataAccessWaterCollectControl.UpdateCollect(c);
                        Console.WriteLine("WaterCollectControl");
                        break;
                    case "OtherCollectControl":
                        DataAccess.DataAccessOtherCollectControl.UpdateCollect(c);
                        Console.WriteLine("OtherCollectControl");
                        break;
                    case "FineCollectControl":
                        DataAccess.DataAccessFineCollectControl.UpdateCollect(c);
                        Console.WriteLine("FineCollectControl");
                        break;
                }
            }
            DataAccessPayment.RegisterPayment(p);
        }

        public static ICollection<Model.CollectControl> SearchByClientId(Model.CollectControl chargetoFind)
        {
            ICollection<Model.CollectControl> waterCollectList = (DataAccess.DataAccessWaterCollectControl.SearchByClientId(chargetoFind)).Cast<Model.CollectControl>().ToList();
            ICollection<Model.CollectControl> fineCollectList = (DataAccess.DataAccessFineCollectControl.SearchByClientId(chargetoFind)).Cast<Model.CollectControl>().ToList();
            ICollection<Model.CollectControl> otherCollectList = (DataAccess.DataAccessOtherCollectControl.SearchByClientId(chargetoFind)).Cast<Model.CollectControl>().ToList();
            
            waterCollectList.ToList().ForEach(i => i.Estructura = ((WaterChargeType)(i.CollectType)).ToString());
            otherCollectList.ToList().ForEach(i => i.Estructura = ((OtherChargeType)(i.CollectType)).ToString());
            fineCollectList.ToList().ForEach(i => i.Estructura = ((FineType)(i.CollectType)).ToString());

            ICollection<Model.CollectControl> genericList = (waterCollectList.Union(fineCollectList).Union(otherCollectList)).ToList();
            if (genericList.Count == 0)
            {
                throw new Exception("El socio no cuenta con deudas pendientes...");
            }

            //foreach (Model.CollectControl charge in genericList)
            //{
            //    switch (charge.CollectType)
            //    {
            //        case 0: charge.Estructura = "Multa - Retraso en el pago de agua";
            //            break;
            //        case 1: charge.Estructura = "Multa - Corte del servicio";
            //            break;
            //        case 2: charge.Estructura = "Multa - Violación del medidor";
            //            break;
            //        case 3: charge.Estructura = "Multa - Retraso en reunión";
            //            break;
            //        case 4: charge.Estructura = "Multa - Inasistencia a reunión";
            //            break;
            //        case 5: charge.Estructura = "Mensualidad    ";
            //            break;
            //    }
            //}

            return (from c in genericList
                    orderby c.CollectPayDate ascending
                    select c).ToList();
        }

        public static void VerifyDates(Model.Payment p)
        {
            if (p.InitialDate == null)
                throw new Exception("Necesita ingresar una fecha inicial para realizar la búsqueda.");
            if (p.FinalDate == null)
                throw new Exception("Necesita ingresar una fecha límite para realizar la búsqueda.");
            if (p.InitialDate > p.FinalDate)
                throw new Exception("Necesita ingresar una fecha válida, la fecha inicial no puede ser posterior a la final.");
            if (p.InitialDate > DateTime.Today)
                throw new Exception("Necesita ingresar una fecha válida, no posterior a la fecha actual.");
            if (p.FinalDate > DateTime.Today)
                throw new Exception("Necesita ingresar una fecha válida, no posterior a la fecha actual.");
        }

        public static ICollection<Model.Payment> SearchPaymentByDatesAndClientId(Model.Payment paymentToFind)
        {
            ICollection<Model.Payment> c;

            //  if (paymentToFind.InitialDate == null)
            //    paymentToFind.InitialDate = DateTime.Today;

            if (paymentToFind.InitialDate.ToString() == "01/01/0001 12:00:00 a.m.")
                paymentToFind.InitialDate = DateTime.Today;

            if (paymentToFind.FinalDate.ToString() == "01/01/0001 12:00:00 a.m.")
                paymentToFind.FinalDate = DateTime.Today;

            //paymentToFind.InitialDate = DateTime.MinValue;
            if (paymentToFind.FinalDate == null)
                paymentToFind.FinalDate = DateTime.MaxValue;

            c = DataAccessCollectControl.SearchPaymentByDatesAndClientId(paymentToFind);

            if (c.Count == 0)
                throw new Exception("No se encontraron resultados de la busqueda...");

            return c;
        }

        public static ICollection<Model.Payment> SearchPaymentByDatesMinusClientId(Model.Payment paymentToFind)
        {
            ICollection<Model.Payment> c;

            c = DataAccessCollectControl.SearchPaymentByDatesMinusClientId(paymentToFind);

            if (c.Count == 0)
                throw new Exception("No se encontraron resultados de la busqueda...");

            return c;
        }

        public static ICollection<Model.CollectControl> SearchCollectsByPaymentId(Model.Payment paymentToFind)
        {
            ICollection<Model.CollectControl> c;
            c = DataAccessCollectControl.SearchCollectsByPaymentId(paymentToFind);

            if (c.Count == 0)
            {
                throw new Exception("No se encontraron resultados de la busqueda...");
            }

            foreach (Model.CollectControl collect in c)
            {
                switch (collect.CollectType)
                {
                    case 0: collect.Estructura = "Multa - Retraso en el pago de agua";
                        break;
                    case 1: collect.Estructura = "Multa - Corte del servicio";
                        break;
                    case 2: collect.Estructura = "Multa - Violación del medidor";
                        break;
                    case 3: collect.Estructura = "Multa - Retraso en reunión";
                        break;
                    case 4: collect.Estructura = "Multa - Inasistencia a reunión";
                        break;
                    case 5: collect.Estructura = "Mensualidad    ";
                        break;
                }
            }

            /*
            return (from c in genericList
                    orderby c.CollectPayDate ascending
                    select c).ToList();*/

            return c;
        }

        public static void ChangeCutSupply(ICollection<CollectControl> collectControls)
        {
            int kardexId = collectControls.First().KardexId;
            DataAccessCutSupply.ChangeCutSupply(kardexId);
        }

        public static bool CheckCutSupply(ICollection<CollectControl> collectControls)
        {
            bool tieneCorte = false;
            int kardexId = collectControls.First().KardexId;

            tieneCorte = DataAccessCutSupply.CheckCutSupply(kardexId);

            return tieneCorte;
        }
    }
}
